package com.jianli.smart.web;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.jianli.smart.core.BeanHelper;
import com.jianli.smart.core.ControllerHelper;
import com.jianli.smart.core.FrameworkConstant;
import com.jianli.smart.core.HelperLoader;
import com.jianli.smart.core.entity.Data;
import com.jianli.smart.core.entity.Handler;
import com.jianli.smart.core.entity.Param;
import com.jianli.smart.core.entity.View;
import com.jianli.smart.core.utils.ArrayUtil;
import com.jianli.smart.core.utils.CodecUtil;
import com.jianli.smart.core.utils.ConfigReader;
import com.jianli.smart.core.utils.JsonUtil;
import com.jianli.smart.core.utils.ReflectionUtil;
import com.jianli.smart.core.utils.StreamUtil;
import com.jianli.smart.core.utils.StringUtil;

/**
 * Servlet implementation class HelloServlet
 */
@WebServlet(urlPatterns = "/*", loadOnStartup = 0)
public class HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        super();
    }
    
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    	HelperLoader.init();
    	
    	ServletContext servletContext = servletConfig.getServletContext();
    	
    	ServletRegistration jspServletRegistration = servletContext.getServletRegistration("jsp");
    	jspServletRegistration.addMapping(ConfigReader.getJspPath() + "*");
    	
    	ServletRegistration defaultRegistration = servletContext.getServletRegistration("default");
    	defaultRegistration.addMapping(ConfigReader.getStaticPath() + "*");
    	super.init();
    }
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		String reqMethod = req.getMethod();
		String reqPath = req.getPathInfo();
		
		Handler handler = ControllerHelper.getHandler(reqMethod, reqPath);
		if(handler != null){
			Class<?> controllerClass = handler.getControllerCLass();
			Object contrllerObj = BeanHelper.getBean(controllerClass);
			Method method = handler.getServiceMethod();
			
			// 设置参数
			Map<String,Object> paramMap = new HashMap<String,Object>();
			Enumeration<String> paramNames = req.getParameterNames();
			while(paramNames.hasMoreElements()){
				String paramName = paramNames.nextElement();
				Object paramValue = req.getParameter(paramName);
				paramMap.put(paramName, paramValue);
			}
			// body里的参数
			String body = CodecUtil.decodeURL(StreamUtil.getString(req.getInputStream()));
			if(StringUtil.isNotEmpty(body)){
				String[] params = StringUtil.splitString(body,"&");
				if(ArrayUtil.isNotEmpty(params)){
					for(String param:params){
						String[] array = param.split("=");
						String paramName = array[0];
						Object paramValue = array[1];
						paramMap.put(paramName, paramValue);
					}
				}
			}
			
			Param param = new Param(paramMap);
			
			Object result = ReflectionUtil.invokeMethod(contrllerObj, method, param);
			
			if(result instanceof View){
				View view = (View) result;
				String path = view.getPath();
				if(StringUtil.isNotEmpty(path)){
					
					// 从根路径开始
					if(path.startsWith("/")){
						resp.sendRedirect(req.getContextPath() + path);
					}else{
						Map<String, Object> model = view.getModel();
						 for(Map.Entry<String, Object> entry:model.entrySet()){
							 req.setAttribute(entry.getKey(), entry.getValue());
							 req.getRequestDispatcher(ConfigReader.getJspPath()+path).forward(req, resp);
						 }
					}
					 
				}
			}else if(result instanceof Data){
				Data data = (Data) result;
				Object model = data.getModel();
				if(model != null){
					resp.setContentType("application/json");
					resp.setCharacterEncoding(FrameworkConstant.UTF_8);
					PrintWriter writer = resp.getWriter();
					String json = JsonUtil.toJSON(model);
					writer.write(json);
					writer.flush();
					writer.close();
				}
			}
		}
	}

}
